package com.example.service.impl;

import com.example.domain.dto.MoneyDTO;
import com.example.domain.dto.PageResponse;
import com.example.domain.dto.product.*;
import com.example.domain.dto.pricelist.PriceListEntryDTO;
import com.example.domain.dto.pricelist.PriceListSummaryDTO;
import com.example.domain.entity.Product;
import com.example.domain.entity.enums.ProductStatus;
import com.example.domain.repository.ProductRepository;
import com.example.domain.repository.UnitRepository;
import com.example.domain.valueobject.DiscountResult;
import com.example.exception.BusinessException;
import com.example.exception.ErrorCode;
import com.example.exception.ResourceNotFoundException;
import com.example.service.PriceListService;
import com.example.service.ProductService;
import com.example.service.PromotionService;

import com.example.util.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品服务实现类
 * 
 * @author Means
 * @since 2025-10-27
 */
@Slf4j
@Service
@Transactional(readOnly = true)
public class ProductServiceImpl implements ProductService {
    
    private final ProductRepository productRepository;
    private final PriceListService priceListService;
    private final PromotionService promotionService;
    private final UnitRepository unitRepository;
    
    public ProductServiceImpl(ProductRepository productRepository, PriceListService priceListService, PromotionService promotionService, UnitRepository unitRepository) {
        this.productRepository = productRepository;
        this.priceListService = priceListService;
        this.promotionService = promotionService;
        this.unitRepository = unitRepository;
    }
    
    // ==================== CRUD操作 ====================
    
    @Override
    @Transactional
    public ProductListItemDTO createProduct(CreateProductRequest request) {
        log.info("创建商品: name={}", request.getName());
        
        // 构建商品实体
        Product product = new Product();
        product.setId(IdGenerator.generate());
        product.setName(request.getName());
        product.setCategory(request.getCategory());
        product.setDescription(request.getDescription());
        product.setStatus(request.getStatus() != null ? request.getStatus() : ProductStatus.ACTIVE);
        
        // 保存
        product = productRepository.save(product);
        
        // 创建 ProductListItemDTO
        ProductListItemDTO productDTO = ProductListItemDTO.from(product);
        // 填充价格信息
        fillPriceInfoForSingle(productDTO);
        
        log.info("商品创建成功: id={}, name={}", product.getId(), product.getName());
        return productDTO;
    }
    
    @Override
    @Transactional
    public ProductListItemDTO updateProduct(String id, UpdateProductRequest request) {
        log.info("更新商品: id={}", id);
        
        // 查询商品
        Product product = productRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new ResourceNotFoundException("商品", id));
        
        // 更新字段（只更新非null字段）
        if (request.getName() != null) {
            product.setName(request.getName());
        }
        if (request.getCategory() != null) {
            product.setCategory(request.getCategory());
        }
        if (request.getDescription() != null) {
            product.setDescription(request.getDescription());
        }
        if (request.getStatus() != null) {
            product.setStatus(request.getStatus());
        }
        
        // 保存
        product = productRepository.save(product);
        
        // 创建 ProductListItemDTO
        ProductListItemDTO productDTO = ProductListItemDTO.from(product);
        // 填充价格信息
        fillPriceInfoForSingle(productDTO);
        
        log.info("商品更新成功: id={}", id);
        return productDTO;
    }
    
    @Override
    @Transactional
    public void deleteProduct(String id) {
        log.info("删除商品: id={}", id);
        
        // 查询商品
        Product product = productRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new ResourceNotFoundException("商品", id));
        
        // 检查商品是否在激活的价目表中
        if (priceListService.isProductInActivePriceList(id)) {
            List<PriceListSummaryDTO> priceLists = priceListService.getActivePriceListsContainingProduct(id);
            String priceListNames = priceLists.stream()
                    .map(PriceListSummaryDTO::getName)
                    .collect(Collectors.joining("、"));
            
            throw new BusinessException(ErrorCode.PRODUCT_IN_ACTIVE_PRICE_LIST,
                    String.format("商品【%s】在以下激活的价目表中：%s。请先从价目表中移除该商品或停用价目表后再删除商品。",
                            product.getName(), priceListNames));
        }
        
        // 软删除
        productRepository.softDelete(id);
        
        log.info("商品删除成功: id={}", id);
    }
    
    @Override
    public ProductListItemDTO getProductById(String id) {
        log.debug("查询商品详情: id={}", id);
        
        Product product = productRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new ResourceNotFoundException("商品", id));
        
        // 使用 fromWithDescription() 创建包含描述的 DTO
        // 不填充价格信息，价格在价目表中单独管理
        return ProductListItemDTO.fromWithDescription(product);
    }
    
    
    @Override
    public boolean existsProduct(String id) {
        return productRepository.findByIdAndNotDeleted(id).isPresent();
    }
    
    // ==================== 查询操作 ====================
    
    @Override
    public PageResponse<ProductListItemDTO> listProducts(ProductSearchRequest request) {
        log.debug("分页查询商品: page={}, size={}", request.getPageOrDefault(), request.getSizeOrDefault());
        
        // 构建分页和排序
        Sort sort = Sort.by(
                "DESC".equalsIgnoreCase(request.getSortDirectionOrDefault()) 
                        ? Sort.Direction.DESC 
                        : Sort.Direction.ASC,
                request.getSortByOrDefault()
        );
        Pageable pageable = PageRequest.of(request.getPageOrDefault(), request.getSizeOrDefault(), sort);
        
        // 查询（根据条件）
        Page<Product> productPage;
        
        if (request.getKeyword() != null && !request.getKeyword().trim().isEmpty()) {
            // 关键词搜索
            productPage = productRepository.searchByNameContaining(request.getKeyword().trim(), pageable);
        } else if (request.getStatus() != null && request.getCategory() != null) {
            // 按状态和分类查询
            productPage = productRepository.findByStatusAndCategoryAndIsDeleted(
                    request.getStatus(), request.getCategory(), false, pageable);
        } else if (request.getStatus() != null) {
            // 按状态查询
            productPage = productRepository.findByStatusAndIsDeleted(request.getStatus(), false, pageable);
        } else if (request.getCategory() != null) {
            // 按分类查询
            productPage = productRepository.findByCategoryAndIsDeleted(request.getCategory(), false, pageable);
        } else {
            // 查询所有（未删除）
            productPage = productRepository.findByIsDeleted(false, pageable);
        }
        
        // 转换为DTO
        PageResponse<ProductListItemDTO> pageResponse = PageResponse.of(productPage, ProductListItemDTO::from);
        
        // 填充价格信息
        fillPriceInfo(pageResponse.getContent());
        
        return pageResponse;
    }
    
    @Override
    public List<ProductListItemDTO> getActiveProducts() {
        log.debug("查询所有已上架商品");
        
        List<Product> products = productRepository.findActiveProducts();
        List<ProductListItemDTO> productDTOs = products.stream()
                .map(ProductListItemDTO::from)
                .collect(Collectors.toList());
        
        // 填充价格信息
        fillPriceInfo(productDTOs);
        
        return productDTOs;
    }
    
    
    @Override
    public List<ProductListItemDTO> searchProducts(String keyword) {
        log.debug("搜索商品: keyword={}", keyword);
        
        if (keyword == null || keyword.trim().isEmpty()) {
            return Collections.emptyList();
        }
        
        List<Product> products = productRepository.findByNameContainingIgnoreCaseAndIsDeletedFalse(keyword.trim());
        List<ProductListItemDTO> productDTOs = products.stream()
                .map(ProductListItemDTO::from)
                .collect(Collectors.toList());
        
        // 填充价格信息
        fillPriceInfo(productDTOs);
        
        return productDTOs;
    }
    
    /**
     * 批量填充商品列表的价格信息
     * 
     * @param productDTOs 商品列表DTO
     */
    private void fillPriceInfo(List<ProductListItemDTO> productDTOs) {
        if (productDTOs == null || productDTOs.isEmpty()) {
            return;
        }
        
        // 获取商品ID列表
        List<String> productIds = productDTOs.stream()
                .map(ProductListItemDTO::getId)
                .collect(Collectors.toList());
        
        // 批量获取价格信息
        Map<String, PriceListEntryDTO> priceMap = priceListService.getCurrentPrices(productIds);
        
        // 填充价格信息到商品列表
        productDTOs.forEach(product -> {
            PriceListEntryDTO priceEntry = priceMap.get(product.getId());
            if (priceEntry != null) {
                // 设置原价（从价目表获取的基准价格）
                MoneyDTO originalPrice = priceEntry.getUnitPrice();
                product.setOriginalPrice(originalPrice);
                product.setUnit(priceEntry.getBaseUnit());
                
                // 填充单位名称
                unitRepository.findByCode(priceEntry.getBaseUnit()).ifPresent(u -> {
                    product.setUnitName(u.getName());
                });
                
                // 计算折扣后的当前价格
                try {
                    DiscountResult discountResult = promotionService.calculateItemDiscount(
                            product.getId(), originalPrice.getAmount());
                    
                if (discountResult.hasDiscount()) {
                    // 有折扣
                    MoneyDTO currentPrice = MoneyDTO.builder()
                            .amount(discountResult.getDiscountedAmount())
                            .currency(originalPrice.getCurrency())
                            .build();
                    product.setCurrentPrice(currentPrice);
                    product.setHasDiscount(true);
                    product.setDiscountDesc(discountResult.getDescription());
                } else {
                    // 无折扣，当前价格等于原价
                    product.setCurrentPrice(originalPrice);
                    product.setHasDiscount(false);
                    product.setDiscountDesc(null);
                }
                } catch (Exception e) {
                    log.warn("计算商品折扣失败: productId={}", product.getId(), e);
                    // 出错时，当前价格等于原价
                    product.setCurrentPrice(originalPrice);
                    product.setHasDiscount(false);
                    product.setDiscountDesc(null);
                }
            }
        });
    }
    
    /**
     * 填充单条商品的价格信息
     * 
     * @param productDTO 商品列表项DTO
     */
    private void fillPriceInfoForSingle(ProductListItemDTO productDTO) {
        if (productDTO == null) {
            return;
        }
        
        // 获取价格信息
        Map<String, PriceListEntryDTO> priceMap = priceListService.getCurrentPrices(
            Collections.singletonList(productDTO.getId()));
        
        PriceListEntryDTO priceEntry = priceMap.get(productDTO.getId());
        if (priceEntry != null) {
            // 设置原价（从价目表获取的基准价格）
            MoneyDTO originalPrice = priceEntry.getUnitPrice();
            productDTO.setOriginalPrice(originalPrice);
            productDTO.setUnit(priceEntry.getBaseUnit());
            
            // 填充单位名称
            unitRepository.findByCode(priceEntry.getBaseUnit()).ifPresent(u -> {
                productDTO.setUnitName(u.getName());
            });
            
            // 计算折扣后的当前价格
            try {
                DiscountResult discountResult = promotionService.calculateItemDiscount(
                        productDTO.getId(), originalPrice.getAmount());
                
                if (discountResult.hasDiscount()) {
                    // 有折扣
                    MoneyDTO currentPrice = MoneyDTO.builder()
                            .amount(discountResult.getDiscountedAmount())
                            .currency(originalPrice.getCurrency())
                            .build();
                    productDTO.setCurrentPrice(currentPrice);
                    productDTO.setHasDiscount(true);
                    productDTO.setDiscountDesc(discountResult.getDescription());
                } else {
                    // 无折扣，当前价格等于原价
                    productDTO.setCurrentPrice(originalPrice);
                    productDTO.setHasDiscount(false);
                    productDTO.setDiscountDesc(null);
                }
            } catch (Exception e) {
                log.warn("计算商品折扣失败: productId={}", productDTO.getId(), e);
                // 出错时，当前价格等于原价
                productDTO.setCurrentPrice(originalPrice);
                productDTO.setHasDiscount(false);
                productDTO.setDiscountDesc(null);
            }
        }
    }
    
    // ==================== 业务操作 ====================
    
    @Override
    @Transactional
    public ProductListItemDTO activateProduct(String id) {
        log.info("上架商品: id={}", id);
        
        Product product = productRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new ResourceNotFoundException("商品", id));
        
        product.setStatus(ProductStatus.ACTIVE);
        product = productRepository.save(product);
        
        // 创建 ProductListItemDTO
        ProductListItemDTO productDTO = ProductListItemDTO.from(product);
        // 填充价格信息
        fillPriceInfoForSingle(productDTO);
        
        log.info("商品上架成功: id={}", id);
        return productDTO;
    }
    
    @Override
    @Transactional
    public ProductListItemDTO deactivateProduct(String id) {
        log.info("下架商品: id={}", id);
        
        Product product = productRepository.findByIdAndNotDeleted(id)
                .orElseThrow(() -> new ResourceNotFoundException("商品", id));
        
        // 检查商品是否在激活的价目表中
        if (priceListService.isProductInActivePriceList(id)) {
            // 获取包含该商品的价目表列表（用于错误提示）
            List<PriceListSummaryDTO> priceLists = 
                    priceListService.getActivePriceListsContainingProduct(id);
            
            String priceListNames = priceLists.stream()
                    .map(PriceListSummaryDTO::getName)
                    .collect(Collectors.joining("、"));
            
            throw new BusinessException(ErrorCode.PRODUCT_IN_ACTIVE_PRICE_LIST, 
                    String.format("商品【%s】在以下激活的价目表中：%s。请先从价目表中移除该商品或停用价目表后再下架商品。", 
                            product.getName(), priceListNames));
        }
        
        product.setStatus(ProductStatus.INACTIVE);
        product = productRepository.save(product);
        
        // 创建 ProductListItemDTO
        ProductListItemDTO productDTO = ProductListItemDTO.from(product);
        // 填充价格信息
        fillPriceInfoForSingle(productDTO);
        
        log.info("商品下架成功: id={}", id);
        return productDTO;
    }
    
    @Override
    public boolean isProductActive(String id) {
        return productRepository.findByIdAndNotDeleted(id)
                .map(product -> product.getStatus() == ProductStatus.ACTIVE)
                .orElse(false);
    }
    
    @Override
    @Transactional
    public void batchActivateProducts(List<String> ids) {
        log.info("批量上架商品: count={}", ids.size());
        
        for (String id : ids) {
            try {
                activateProduct(id);
            } catch (ResourceNotFoundException e) {
                log.warn("商品不存在，跳过: id={}", id);
            }
        }
        
        log.info("批量上架完成");
    }
    
    @Override
    @Transactional
    public void batchDeactivateProducts(List<String> ids) {
        log.info("批量下架商品: count={}", ids.size());
        
        for (String id : ids) {
            try {
                deactivateProduct(id);
            } catch (ResourceNotFoundException e) {
                log.warn("商品不存在，跳过: id={}", id);
            }
        }
        
        log.info("批量下架完成");
    }
}

